#include <iostream>
#include <immintrin.h>
#include <xmmintrin.h> //SSE
#include <emmintrin.h> //SSE2
#include <pmmintrin.h> //SSE3
#include <tmmintrin.h> //SSSE3
#include <smmintrin.h> //SSE4.1
#include <nmmintrin.h> //SSSE4.2
#include <immintrin.h> //AVX、AVX
#include <pthread.h>
#include<semaphore.h>

#include<fstream>
#include<string>
#include<vector>
#include<sys/time.h>
#include<math.h>


#include<queue>
using namespace std; 
int n;//矩阵大小
unsigned int** zi;
unsigned int** bei;
int publickLie = 0;


queue<int>mission_pool;
bool* choosing;
int* ticketNum;
int pThreadNum;
bool missionFinished = 0;
bool** ziNull;
bool* ziUsed;
bool* fuzhi;
bool* wetherThisHangIsOk;

int beginHang = 0;


sem_t sem_leader;
sem_t* sem_Divsion;
sem_t* sem_finish;


typedef struct
{
    int howmany; //每轮多少行
    int t_id; // 线程 id
    int zilie;
    int lie;
}threadParam_t;


int type = 0;
pthread_t* handle;
threadParam_t* param;
int aPos, bPos;

int getTicketNum()
{
    int max = 0;
    for (int i = 0; i < pThreadNum; i++) 
    {
        if (max < ticketNum[i])
            max = ticketNum[i];
    }
    return max + 1;
}


string getbeiAddr(int which)
{
    switch (which) {
    case 1:
        return "/e/搞死小圆/Groebner/测试样例1 矩阵列数130，非零消元子22，被消元行8/被消元行.txt";
    case 2:
        return "/e/搞死小圆/Groebner/测试样例2 矩阵列数254，非零消元子106，被消元行53/被消元行.txt";
    case 3:
        return "/e/搞死小圆/Groebner/测试样例3 矩阵列数562，非零消元子170，被消元行53/被消元行.txt";
    case 4:
        return "/e/搞死小圆/Groebner/测试样例4 矩阵列数1011，非零消元子539，被消元行263/被消元行.txt";
    case 5:
        return "/e/搞死小圆/Groebner/测试样例5 矩阵列数2362，非零消元子1226，被消元行453/被消元行.txt";
    case 6:
        return "/e/搞死小圆/Groebner/测试样例6 矩阵列数3799，非零消元子2759，被消元行1953/被消元行.txt";
    case 7:
        return "/e/搞死小圆/Groebner/测试样例7 矩阵列数8399，非零消元子6375，被消元行4535/被消元行.txt";
    case 8:
        return "/e/搞死小圆/Groebner/测试样例8 矩阵列数23045，非零消元子18748，被消元行14325/被消元行.txt";
    case 9:
        return "/e/搞死小圆/Groebner/测试样例9 矩阵列数37960，非零消元子29304，被消元行14921/被消元行.txt";
    case 10:
        return "/e/搞死小圆/Groebner/测试样例10 矩阵列数43577，非零消元子39477，被消元行54274/被消元行.txt";
    case 11:
        return "/e/搞死小圆/Groebner/测试样例11 矩阵列数85401，非零消元子5724，被消元行756/被消元行.txt";
    }
}
string getziAddr(int which)
{
    switch (which) {
    case 1:
        return "/e/搞死小圆/Groebner/测试样例1 矩阵列数130，非零消元子22，被消元行8/消元子.txt";
    case 2:
        return "/e/搞死小圆/Groebner/测试样例2 矩阵列数254，非零消元子106，被消元行53/消元子.txt";
    case 3:
        return "/e/搞死小圆/Groebner/测试样例3 矩阵列数562，非零消元子170，被消元行53/消元子.txt";
    case 4:
        return "/e/搞死小圆/Groebner/测试样例4 矩阵列数1011，非零消元子539，被消元行263/消元子.txt";
    case 5:
        return "/e/搞死小圆/Groebner/测试样例5 矩阵列数2362，非零消元子1226，被消元行453/消元子.txt";
    case 6:
        return "/e/搞死小圆/Groebner/测试样例6 矩阵列数3799，非零消元子2759，被消元行1953/消元子.txt";
    case 7:
        return "/e/搞死小圆/Groebner/测试样例7 矩阵列数8399，非零消元子6375，被消元行4535/消元子.txt";
    case 8:
        return "/e/搞死小圆/Groebner/测试样例8 矩阵列数23045，非零消元子18748，被消元行14325/消元子.txt";
    case 9:
        return "/e/搞死小圆/Groebner/测试样例9 矩阵列数37960，非零消元子29304，被消元行14921/消元子.txt";
    case 10:
        return "/e/搞死小圆/Groebner/测试样例10 矩阵列数43577，非零消元子39477，被消元行54274/消元子.txt";
    case 11:
        return "/e/搞死小圆/Groebner/测试样例11 矩阵列数85401，非零消元子5724，被消元行756/消元子.txt";

    }
}
int getHang(int which)
{
    switch (which)
    {
    case 1:
        return 8;
    case 2:
        return 53;
    case 3:
        return 53;
    case 4:
        return 263;
    case 5:
        return 453;
    case 6:
        return 1953;
    case 7:
        return 4535;
    case 8:
        return 14325;
    case 9:
        return 14291;
    case 10:
        return 54274;
    case 11:
        return 756;
    }
}
int getLie(int which)
{
    switch (which)
    {
    case 1:
        return 130;
    case 2:
        return 254;
    case 3:
        return 562;
    case 4:
        return 1011;
    case 5:
        return 2362;
    case 6:
        return 3799;
    case 7:
        return 8399;
    case 8:
        return 23075;
    case 9:
        return 37960;
    case 10:
        return 43577;
    case 11:
        return 85401;
    }
}


void showLie(unsigned int* m, int lie)
{
    for (int i = 0; i < lie; i++)
    {
        cout << m[i] << " ";
    }
    cout << endl;
}
unsigned int** init(int &hang, int &lie)
{
    unsigned int** m = new unsigned int* [hang];
    for (int i = 0; i < hang; i++)
    {
        m[i] = new unsigned int[lie];
        for (int p = 0; p < lie; p++)
        {
            m[i][p] = 0;
        }
    }
    return m;
}
int qujian(int &nowliePos, int &lie)
{
    //97,65,33,1
    //假设不弄32了，分成每五个一组。那么125是和129一样都是第0组的.130 - 125 - 1 /5 = 0
    return (lie - nowliePos - 1) / 32;
}
int liePos(int &nowliePos, int &lie)
{
    //还是假设五个一组。120是第1组第4位，130 - (1*5 + 120) = 5
    return lie - (((lie - nowliePos - 1) / 32) * 32 + nowliePos) - 1;
}
unsigned int bit2int(int*& m)//统一在左边的是高位
{
    unsigned int result = 0;
    for (int i = 0; i < 32; i++)
    {
        if (m[i])result += pow(2, 31 - i);
    }
    return result;
}
void showM(unsigned int** &m, int &hang, int &lie)
{
    for (int i = 0; i < hang; i++)
    {
        showLie(m[i], lie);
        cout << endl;
    }
}
int* int2bit(unsigned int &decimal_num)
{
    int* pos = new int[32];
    unsigned int mask = 1 << 31; // 定义掩码，初始值为1左移31位
    for (int i = 0; i < 32; i++) {
        // 判断当前位是0还是1，并输出
        if ((decimal_num & mask) == 0) {
            pos[i] = 0;
        }
        else {
            pos[i] = 1;
        }
        // 将掩码右移一位，判断下一位
        mask = mask >> 1;
    }
    return pos;
}
unsigned int** write(string &beiAddr, int &beihang, int &beilie)
{
    int lie = (beilie / 32 * 32 == beilie) ? beilie / 32 : beilie / 32 + 1;
    int yu = lie - beilie;
    unsigned int** m = new unsigned int* [beihang];
    for (int i = 0; i < beihang; i++)
    {
        m[i] = new unsigned int[lie];
        for (int p = 0; p < lie; p++)
            m[i][p] = 0;
    }
    ifstream fin;
    fin.open(beiAddr.c_str(), ios::in);
    if (!fin)
    {
        cout << "fuck!" << endl;
    }
    int* pos = new int[32];
    for (int i = 0; i < 32; i++)
        pos[i] = 0;
    char ch;
    int temp = 0, nowPos = 0, bitclimiter = 0, whetherBegin = 1, nowQujian = 0, lastQujian = 0;
    while (fin.get(ch))
    {
        if (ch >= '0' && ch <= '9')
        {
            temp *= 10;
            temp += ch - '0';
        }
        else if (ch == ' ')
        {
            if (whetherBegin)
            {
                lastQujian = qujian(temp, beilie); //注意这里穿的是int的列长度。
                bitclimiter = liePos(temp, beilie);//算出了temp所在的区间的位置。
                pos[bitclimiter] = 1;//该区间下对应位置记为1
                whetherBegin = 0;
            }
            else
            {
                nowQujian = qujian(temp, beilie);//算出了temp所在的区间
                if (nowQujian != lastQujian)
                {
                    m[nowPos][lastQujian] = bit2int(pos);
                    for (int i = 0; i < 32; i++)
                        pos[i] = 0;
                }
                bitclimiter = liePos(temp, beilie);//算出了temp所在的区间的位置。
                pos[bitclimiter] = 1;//该区间下对应位置记为1
                lastQujian = nowQujian;
            }
            temp = 0;
        }
        else if (ch == '\n')
        {
            m[nowPos][lastQujian] = bit2int(pos);
            for (int i = 0; i < 32; i++)
                pos[i] = 0;
            whetherBegin = 1;
            nowPos++;
            temp = 0;
            nowQujian = 0;
            lastQujian = 0;
        }
    }
    fin.close();
    return m;
}


int* pos;
streampos UpdateZi(int &howmany, int &zilie, int &lie, int &beginHang, ifstream& fin, streampos &headPos)
{
    //ifstream fin;
    //fin.open(addr.c_str(), ios::in);
    for (int i = 0; i < howmany; i++)
        for (int p = 0; p < lie; p++)
            zi[i][p] = 0;
    for (int i = 0; i < 32; i++)
        pos[i] = 0;
    streampos nowHead = headPos;
    fin.seekg(headPos);
    char ch;
    int temp = 0, nowPos = 0, bitclimiter = 0, whetherBegin = 1, nowQujian = 0, lastQujian = 0, thisishang = 0, dotimes = 0;
    while (dotimes < howmany && fin.get(ch))
    {
        if (ch >= '0' && ch <= '9')
        {
            temp *= 10;
            temp += ch - '0';
        }
        else if (ch == ' ')
        {
            if (whetherBegin)
            {
                if (temp < beginHang - howmany)
                {
                    break;
                }
                else
                {
                    lastQujian = qujian(temp, zilie);
                    bitclimiter = liePos(temp, zilie);
                    pos[bitclimiter] = 1;
                    whetherBegin = 0;
                    thisishang = beginHang - temp - 1;
                }
            }
            else
            {
                nowQujian = qujian(temp, zilie);//算出了temp所在的区间
                if (nowQujian != lastQujian)
                {
                    zi[thisishang][lastQujian] = bit2int(pos);
                    for (int i = 0; i < 32; i++)
                        pos[i] = 0;
                }
                bitclimiter = liePos(temp, zilie);//算出了temp所在的区间的位置。
                pos[bitclimiter] = 1;//该区间下对应位置记为1
                lastQujian = nowQujian;
            }
            temp = 0;
        }
        else if (ch == '\n')
        {
            nowHead = fin.tellg();
            zi[thisishang][lastQujian] = bit2int(pos);
            for (int i = 0; i < 32; i++)
                pos[i] = 0;
            whetherBegin = 1;
            dotimes++;
            temp = 0;
            nowQujian = 0;
            lastQujian = 0;
        }
    }
    //fin.close();
    return nowHead;
}
int findinthead(unsigned int &num, int &lie, int &qujian)
{
    int* pos = int2bit(num);
    for (int i = 0; i < 32; i++)
    {
        if (pos[i])
        {
            return lie - qujian * 32 - i - 1;
        }
    }
    return -1;
}
int findHead(unsigned int*& m, int &lie)//这里的列是01串的列
{
    for (int i = 0; i < lie; i++)
    {
        if (m[i])
        {
            return findinthead(m[i], lie, i);
        }
    }
    return -1;
}



int firstNotZeroPos = 0;
bool isNotNull(unsigned int*& m, int& lie)
{
    for (int i = 0; i < lie; i++)
    {
        if (m[i])
        {
            firstNotZeroPos = i;
            return 1;
        }
    }
    return 0;
}
void AsubB(unsigned int* &a, unsigned int*& b, int &lie)
{
    for (int i = 0; i < lie; i++)
    {
        a[i] = a[i] ^ b[i];
    }
}
void bingxingAsubB(unsigned int* &a, unsigned int*& b, int &lie)
{
    /*int i = 0;
    __m256i t1, t2;
    for (i = 0; i + 8 < lie; i += 8)
    {
        t1 = _mm256_loadu_si256((__m256i*) & a[i]);
        t2 = _mm256_loadu_si256((__m256i*) & b[i]);
        t1 = _mm256_xor_si256(t1, t2);
        _mm256_storeu_si256((__m256i*) & a[i], t1);
    }
    for (; i < lie; i++)
    {
        a[i] = (a[i] == b[i]) ? 0 : 1;
    }


    int i = 0;
    for (i = 0; i + 4 < lie; i += 4)
    {
        __m128i t1 = _mm_loadu_si128((__m128i*) & a[i]);
        __m128i t2 = _mm_loadu_si128((__m128i*) & b[i]);
        t1 = _mm_xor_si128(t1, t2);
        _mm_storeu_si128((__m128i*) & a[i], t1);
    }

    for (; i < lie; i++)
    {
        a[i] = (a[i] == b[i]) ? 0 : 1;
    }*/
}

void testShow(unsigned int** m, int hang, int lie, int lieOf01)
{
    int* temp;
    for (int i = 0; i < hang; i++)
    {
        for (int p = 0; p < lie; p++)
        {
            temp = int2bit(m[i][p]);
            for (int q = 0; q < 32; q++)
            {
                if (temp[q])
                {
                    cout << lieOf01 - 32 * p - q - 1 << " ";
                }
            }
        }
        cout << endl;
    }
}




void* threadFunc(void* param)
{
    threadParam_t* p = (threadParam_t*)param;
    int t_id = p->t_id;
    int howmany = p->howmany;
    int zilie = p->zilie;
    int lie = p->lie;
    bool whetherBreak = 0, whetherJumpOut = 0;

    int nowBeiPos = 0, nowHead = 0, ziHead = 0;

    while (1)
    {
        //当任务没有完成，主线没有发布任务的时候就卡在这里
        sem_wait(&sem_Divsion[t_id]);//等待主线程命令开始任务。
        //当主线程发布任务，就执行下面的循环直到当前loop任务做完。然后回到这里接着卡住。
        if (missionFinished)
        {
            break;
        }
        while (1)
        {
            if (mission_pool.size())//如果任务池里还有东西，那么就取用！
            {

                /********************选数阶段***********************/

                choosing[t_id] = 1;
                ticketNum[t_id] = getTicketNum();//注意，如果两个线程同时访问这个函数可能会导致两个线程取到一样的号码
                choosing[t_id] = 0;
                for (int i = 0; i < pThreadNum; i++)
                {
                    while (choosing[i])
                        continue;
                    while (ticketNum[i] != 0 && //如果i已经正在执行它的任务了，那么不用考虑i，直接看下一个线程。
                        (ticketNum[i] < ticketNum[t_id] || //如果i的号码比t_id的小，那么t_id等待
                            (ticketNum[i] == ticketNum[t_id] && i < t_id) //如果i和t_id娶到了同样的号码，但是i的序号在t_id前面，那么t_id还是等待。
                            ))
                        continue;
                }
                if (mission_pool.size() == 0)
                {
                    continue;
                }
                //现在可以进入选择任务了
                nowBeiPos = mission_pool.front();
                mission_pool.pop();
                //取完任务以后，释放号码。
                ticketNum[t_id] = 0;
                /********************选数阶段***********************/
                whetherBreak = 0;
                for (int ziPos = beginHang - 1; ziPos >= beginHang - howmany; ziPos--)
                {
                    nowHead = findHead(bei[nowBeiPos], zilie);
                    if (nowHead >= beginHang - howmany && nowHead < beginHang)
                    {
                        while (1)
                        {
                            if (isNotNull(zi[beginHang - nowHead - 1], lie))
                            {
                                AsubB(bei[nowBeiPos], zi[beginHang - nowHead - 1], lie);
                                break;//如果不用对消元子修改，那非常喜欢，直接减完然后break就好了。
                            }
                            else
                            {
                                //这里由于要涉及到对公共资源zi的修改，所以也需要面包店算法。如果有线程已经在访问这个空的消元子了，那么本线程直接不用考虑了，
                                //等待那个先来的线程填入这个空的消元子之后，直接把这个消元子拿来用。与一开始的取任务不同，这里只需要第一个来的线程进行这一步
                                //就足够了。
                                if (ziUsed[beginHang - nowHead - 1])//如果这列已经有人了，那么直接continue；
                                {
                                    continue;
                                }
                                else
                                {
                                    whetherJumpOut = 0;
                                    ziUsed[beginHang - nowHead - 1] = 1;//抢到优先权的线程直接把路毒死。
                                    //这样做存在可能，就是如果有多个线程同时进来，那么就需要用到下面的内容了。
                                    //但这可以接受，我不能接受的是，在进行比较的时候，突然又有新的线程加进来，直接导致混乱！
                                    fuzhi[t_id] = 1;
                                    ziNull[beginHang - nowHead - 1][t_id] = 1;//把这个用来阻塞的矩阵的对应线程位置赋值为1.
                                    fuzhi[t_id] = 0;
                                    for (int zuse = 0; zuse < t_id; zuse++)
                                    {
                                        while (fuzhi[zuse])
                                            continue;
                                        if (ziNull[beginHang - nowHead - 1][zuse])//如果有比t_id小的线程占据了NULL，那么就jumpout。
                                        {
                                            whetherJumpOut = 1;
                                            break;
                                        }
                                    }
                                    if (whetherJumpOut)
                                        continue;
                                }


                                wetherThisHangIsOk[nowBeiPos] = 1;
                                for (int qqq = 0; qqq < lie; qqq++)
                                {
                                    zi[beginHang - nowHead - 1][qqq] = bei[nowBeiPos][qqq];
                                }
                                whetherBreak = 1;
                                break;
                            }
                        }
                    }
                    else 
                        whetherBreak = 1;

                    if (whetherBreak)
                        break;
                }
            }
            else
            {
                sem_post(&sem_leader);//完工，通知主线程。
                break;//退出当前loop的循环。
            }
        }
    }

    pthread_exit(NULL);
}

double common(int howmany, int beihang, int beilie, int zihang, int zilie, int whichTextIsNow, int bingOrCom)
{
    struct timeval t1, t2;
    double timeuse = 0;
    string ziAddr = getziAddr(whichTextIsNow);
    ifstream fin;
    fin.open(ziAddr.c_str(), ios::in);
    int lie = (beilie / 32 * 32 == beilie) ? beilie / 32 : beilie / 32 + 1;
    zi = init(howmany, lie);
    int beginHang = zihang;
    int times = zihang / howmany;
    streampos headPos = 0;
    bool* wetherThisHangIsOk = new bool[beihang];
    for (int i = 0; i < beihang; i++)
        wetherThisHangIsOk[i] = 0;
    int nowHead = 0, ziHead = 0;
    int beishufuck = 1;
    for (int cycles = 0; cycles < times; cycles++)
    {
        if (times * beishufuck / 10 <= cycles)
        {
            cout << beishufuck << "0%" << endl;
            beishufuck++;
        }

        beginHang = zihang - cycles * howmany;
        headPos = UpdateZi(howmany, zilie, lie, beginHang, fin, headPos);//这样子消元子就被更新了。
        gettimeofday(&t1, NULL);
        for (int beiPos = 0; beiPos < beihang; beiPos++)
        {
            if (wetherThisHangIsOk[beiPos])
            {
                continue;
            }
            for (int ziPos = beginHang - 1; ziPos >= beginHang - howmany; ziPos--)
            {
                nowHead = findHead(bei[beiPos], zilie);
                if (nowHead >= beginHang - howmany && nowHead < beginHang)
                {
                    //zi[beginHang - nowHead - 1]是数组。我们要判断这玩意是不是空的
                    if (isNotNull(zi[beginHang - nowHead - 1], lie))
                    {
                        //bingxingAsubB(bei[beiPos], zi[beginHang - nowHead - 1], lie);
                        AsubB(bei[beiPos], zi[beginHang - nowHead - 1], lie);
                        //if (bingOrCom) bingxingAsubB(bei[beiPos], zi[beginHang - nowHead - 1], lie);
                        //else AsubB(bei[beiPos], zi[beginHang - nowHead - 1], lie);
                    }
                    else
                    {
                        wetherThisHangIsOk[beiPos] = 1;
                        for (int qqq = 0; qqq < lie; qqq++)
                        {
                            zi[beginHang - nowHead - 1][qqq] = bei[beiPos][qqq];
                        }
                        break;
                    }
                }
                else break;
            }
        }
        gettimeofday(&t2, NULL);
        timeuse += (t2.tv_sec - t1.tv_sec) + (double)(t2.tv_usec - t1.tv_usec) / 1000000.0;
    }
    return timeuse;
}

double pthreadBingxing(int howmany, int beihang, int beilie, int zihang, int zilie, int whichTextIsNow, int bingOrCom)
{
    struct timeval t1, t2;
    double timeuse = 0;
    string ziAddr = getziAddr(whichTextIsNow);
    ifstream fin;
    fin.open(ziAddr.c_str(), ios::in);
    int lie = (beilie / 32 * 32 == beilie) ? beilie / 32 : beilie / 32 + 1;
    zi = init(howmany, lie);
    beginHang = zihang;
    int times = zihang / howmany;
    streampos headPos = 0;
    wetherThisHangIsOk = new bool[beihang];
    for (int i = 0; i < beihang; i++)
        wetherThisHangIsOk[i] = 0;

    ziNull = new bool* [howmany];
    ziUsed = new bool[howmany];
    for (int i = 0; i < howmany; i++)
    {
        ziNull[i] = new bool[pThreadNum];
    }


    /*pthread初始化操作*/
    publickLie = lie;
    handle = new pthread_t[pThreadNum];
    param = new threadParam_t[pThreadNum];
    fuzhi = new bool[pThreadNum];
    for (int id = 0; id < pThreadNum; id++)
    {
        param[id].t_id = id;
        param[id].howmany = howmany;
        param[id].zilie = zilie;
        param[id].lie = lie;
        pthread_create(&handle[id], NULL, threadFunc, (void*)&param[id]);
    }
    /*pthread初始化操作*/


    int beishufuck = 1;


    for (int cycles = 0; cycles < times; cycles++)
    {
        if (times * beishufuck / 10 <= cycles)
        {
            cout << beishufuck << "0%" << endl;
            beishufuck++;
        }


        beginHang = zihang - cycles * howmany;
        headPos = UpdateZi(howmany, zilie, lie, beginHang, fin, headPos);

        /*************************初始化任务池****************************/

        for (int i = 0; i < beihang; i++)
        {
            if (wetherThisHangIsOk[i])
            {
                continue;
            }
            mission_pool.push(i);
        }

        /*************************初始化任务池****************************/

        for (int i = 0; i < pThreadNum; i++)
        {
            choosing[i] = 0;
            ticketNum[i] = 0;
        }


        for (int i = 0; i < howmany; i++)
        {
            ziUsed[i] = 0;
            for (int p = 0; p < pThreadNum; p++)
            {
                ziNull[i][p] = 0;
            }
        }


        gettimeofday(&t1, NULL);

        //主线程开始叫各位子线程开始工作了！
        //由于之前在初始化mission_pool的时候，已经自动去除了wetherThisHangIsOk为1，也就是已经完成校园了的行，所以这里不用考虑。
        for (int i = 0; i < pThreadNum; i++)
            sem_post(&sem_Divsion[i]);//发布任务


        for (int i = 0; i < pThreadNum; i++)
            sem_wait(&sem_leader);//等待各个子线程完成。




        gettimeofday(&t2, NULL);
        timeuse += (t2.tv_sec - t1.tv_sec) + (double)(t2.tv_usec - t1.tv_usec) / 1000000.0;
    }
    missionFinished = 1;
    for (int i = 0; i < pThreadNum; i++)
        sem_post(&sem_Divsion[i]);//还要再发布一次，让各个线程退出来。




    for (int id = 0; id < pThreadNum; id++)
        pthread_join(handle[id], NULL);



    //testShow(bei, beihang, lie, beilie);
    return timeuse;
}

int main()
{

    type = 1;
    pThreadNum = 3;
    if (type)
    {
        sem_Divsion = new sem_t[pThreadNum];
        sem_finish = new sem_t[pThreadNum];
        sem_init(&sem_leader, 0, 0);
        choosing = new bool[pThreadNum];
        ticketNum = new int[pThreadNum];
        for (int i = 0; i < pThreadNum; i++)
        {
            sem_init(&sem_Divsion[i], 0, 0);
            sem_init(&sem_finish[i], 0, 0);
        }
    }
    pos = new int[32];

    double time = 0;
    for (int i = 7; i <= 7; i++)
    {
        int beihang, beilie, zihang, zilie;
        int whichTextIsNow = i;
        beihang = getHang(whichTextIsNow);
        beilie = zihang = zilie = getLie(whichTextIsNow);
        string beiAddr = getbeiAddr(whichTextIsNow);
        bei = write(beiAddr, beihang, beilie);

        int howmany = 20;

        if (type)
        {
            time = pthreadBingxing(howmany, beihang, beilie, zihang, zilie, whichTextIsNow, 1);
        }
        else
        {
            time = common(howmany, beihang, beilie, zihang, zilie, whichTextIsNow, 1);
        }

        cout << time << endl;

    }





    if (type)
    {
        sem_destroy(&sem_leader);
        for (int i = 0; i < pThreadNum; i++)
        {
            sem_destroy(&sem_Divsion[i]);
            sem_destroy(&sem_finish[i]);
        }
    }
    return 0;
}
